/*
 * @Author: aggfb 714740235@qq.com
 * @Date: 2024-11-21 07:22:28
 * @LastEditors: aggfb 714740235@qq.com
 * @LastEditTime: 2025-03-01 22:28:05
 * @FilePath: \wire_receiver_box\bsp\bsp_uart.c
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */

#include "bsp_uart.h"
#include "ringbuffer.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"

static void bsp_usart0_init(bsp_uart_driver_t *drv);
static void bsp_usart1_init(bsp_uart_driver_t *drv);
static void bsp_usart2_init(bsp_uart_driver_t *drv);
static void bsp_usart3_init(bsp_uart_driver_t *drv);

static uint32_t prod_ioctrl(bsp_uart_driver_t *drv, uint8_t cmd, uint32_t *val);
static int16_t prod_read(bsp_uart_driver_t *drv, uint8_t *buff, uint16_t len);
static int16_t prod_write(bsp_uart_driver_t *drv, uint8_t *buff, uint16_t len);
static int16_t prod_irq_cb(bsp_uart_driver_t *drv, uint8_t *buff, uint16_t len);

static bsp_uart_driver_t usart_driver[] = {
    {
        .uart_id = USART0,
        .ops = {
            .ioctrl = prod_ioctrl,
            .read = prod_read,
            .write = prod_write,
            .irq_cb = prod_irq_cb,
        },   
        .port ={
            .rx_queue = NULL,
        }     
    },
    {
        .uart_id = UART3,
        .ops = {
            .ioctrl = prod_ioctrl,
            .read = prod_read,
            .write = prod_write,
            .irq_cb = prod_irq_cb,
        },
        .port ={
            .rx_queue = NULL,
        }       
    },
};

bsp_uart_driver_t *lora_drv(void)
{
    return (&usart_driver[0]);
}

bsp_uart_driver_t *scan_drv(void)
{
    return (&usart_driver[1]);
}

uint32_t prod_ioctrl(bsp_uart_driver_t *drv, uint8_t cmd, uint32_t *val)
{
    switch (cmd)
    {
        case IOCTRL_CMD: 
        break;
        case IOCTRL_GET_RX_BUFF_SIZE:
            *val = uxQueueMessagesWaiting(drv->port.rx_queue);    
        break;
        case IOCTRL_GET_RX_BUFF_BYTE:
            xQueueReceive(drv->port.rx_queue, val, 0); 
        break;
        case IOCTRL_SET_TX_BUFF:
            xQueueSend(drv->port.tx_queue, (struct _protocol*)(val), 0); 
        break;
        default:
        break;
    }
		return 0;
}

int16_t prod_read(bsp_uart_driver_t *drv, uint8_t *buff, uint16_t len)
{
    uint8_t i = 0;
    for(i = 0; i < len; i++)
    {
        BaseType_t res = xQueueReceive(drv->port.rx_queue, buff, portMAX_DELAY); 
    }
    return i;
}

int16_t prod_write(bsp_uart_driver_t *drv, uint8_t *buff, uint16_t len)
{
    for (uint16_t i = 0; i < len; i++)
    {
        while(RESET == usart_flag_get(drv->uart_id, USART_FLAG_TBE));
        usart_data_transmit(drv->uart_id, *buff);
        buff++;
    }
    return len;
}

static int16_t prod_irq_cb(bsp_uart_driver_t *drv, uint8_t *buff, uint16_t len)
{
    BaseType_t xHigherPriorityTaskWoken;
    for (uint16_t i = 0; i < len; i++)
    {
        xQueueSendFromISR(drv->port.rx_queue, &(*buff), &xHigherPriorityTaskWoken);
        if (xHigherPriorityTaskWoken == pdTRUE) 
        {
            //portYIELD();
        }
        buff++;
    }
    return len;
}

int bsp_uart_register_driver(bsp_uart_driver_t *drv)
{
    if(drv->uart_id == USART0)
    {
        bsp_usart0_init(drv);      
    }
    else if(drv->uart_id == USART1)
    {
        bsp_usart1_init(drv);    
    }
    else if(drv->uart_id == USART2)
    {
        bsp_usart2_init(drv);    
    }
    else if(drv->uart_id == UART3)
    {
        bsp_usart3_init(drv);    
    }
    else
    {
        return -1;
    }

    /* 创建接收缓存 */
    if(drv->port.rx_queue == NULL)
    {
        drv->port.rx_queue = xQueueCreate(RX_SIZE, sizeof(uint8_t));
    }

    /* 创建发送队列缓存 */
    if(drv->port.tx_queue == NULL)
    {
        drv->port.tx_queue = xQueueCreate(4, sizeof(struct _protocol));
    }

    return 0;
}

void bsp_uart_unregister_driver(bsp_uart_driver_t *drv)
{
}

/*******************************************************************
 * 函数名: bsp_usart0_init()
 * 功 能:
 * 输 入:
 * 输 出:
 *******************************************************************/
static void bsp_usart0_init(bsp_uart_driver_t *drv)
{
    rcu_periph_clock_enable(RCU_USART0);
    rcu_periph_clock_enable(RCU_GPIOA);
    rcu_periph_clock_enable(RCU_DMA1);

    gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_9);
    gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_10);

    /* TX */
    gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP,GPIO_PIN_9);
    gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_9);

    /* RX */
    gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP,GPIO_PIN_10);
    gpio_output_options_set(GPIOA, GPIO_MODE_INPUT, GPIO_OSPEED_50MHZ,GPIO_PIN_10);

    usart_deinit(USART0);
    usart_baudrate_set(USART0, 9600U);
    usart_receive_config(USART0, USART_RECEIVE_ENABLE);
    usart_transmit_config(USART0, USART_TRANSMIT_ENABLE);
    usart_dma_receive_config(USART0, USART_RECEIVE_DMA_ENABLE);
    usart_enable(USART0);

	dma_single_data_parameter_struct dma_init_struct;
#if 0
    // TX    
    dma_deinit(DMA1, DMA_CH5);
    dma_struct_para_init(&dma_init_struct);
    dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL;
    dma_init_struct.memory_addr = NULL;
    dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
    dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;
    dma_init_struct.number = 0;
    dma_init_struct.periph_addr = (uint32_t)&USART_DATA(USART0);
    dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
    dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT;
    dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
    dma_init(DMA1, DMA_CH5, &dma_init_struct);
#endif
    // RX
    dma_deinit(DMA1, DMA_CH5);

    dma_init_struct.memory0_addr = (uint32_t)(&drv->port.rx_buff);
    dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
    dma_init_struct.number = RX_SIZE;
    dma_init_struct.periph_addr = (uint32_t)&USART_DATA(USART0);
    dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
    dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
    dma_init_struct.periph_memory_width = DMA_PERIPH_WIDTH_8BIT;
    dma_init_struct.direction = DMA_PERIPH_TO_MEMORY;
    dma_single_data_mode_init(DMA1, DMA_CH5, &dma_init_struct);

    dma_channel_subperipheral_select(DMA1, DMA_CH5, DMA_SUBPERI4);
    dma_circulation_disable(DMA1, DMA_CH5);
    dma_channel_enable(DMA1, DMA_CH5);

    nvic_irq_enable(USART0_IRQn, 5, 0);
    usart_interrupt_enable(USART0, USART_INT_IDLE);

}

/*******************************************************************
 * 函数名: bsp_usart1_init()
 * 功 能:
 * 输 入:
 * 输 出:
 *******************************************************************/
static void bsp_usart1_init(bsp_uart_driver_t *drv)
{
    rcu_periph_clock_enable(RCU_USART0);
    rcu_periph_clock_enable(RCU_GPIOA);
    rcu_periph_clock_enable(RCU_DMA0);

    gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_9);
    gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_10);

    /* TX */
    gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP,GPIO_PIN_9);
    gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_9);

    /* RX */
    gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP,GPIO_PIN_10);
    gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_10);

    usart_deinit(USART0);
    usart_baudrate_set(USART0, 115200U);
    usart_word_length_set(USART0, USART_WL_8BIT);
    usart_stop_bit_set(USART0, USART_STB_1BIT);
    usart_parity_config(USART0, USART_PM_NONE);
    usart_hardware_flow_rts_config(USART0, USART_RTS_DISABLE);
    usart_hardware_flow_cts_config(USART0, USART_CTS_DISABLE);
    usart_receive_config(USART0, USART_RECEIVE_ENABLE);
    usart_transmit_config(USART0, USART_TRANSMIT_ENABLE);
    usart_enable(USART0);
	#if 0
    // TX
    dma_parameter_struct dma_init_struct;
    dma_deinit(DMA0, DMA_CH3);
    dma_struct_para_init(&dma_init_struct);
    dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL;
    dma_init_struct.memory_addr = NULL;
    dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
    dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;
    dma_init_struct.number = 0;
    dma_init_struct.periph_addr = (uint32_t)&USART_DATA(USART0);
    dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
    dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT;
    dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
    dma_init(DMA0, DMA_CH3, &dma_init_struct);
    // RX
    dma_deinit(DMA0, DMA_CH4);
    dma_struct_para_init(&dma_init_struct);
    dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY;
    dma_init_struct.memory_addr = (uint32_t)(drv->port.rx_buff);
    dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
    dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;
    dma_init_struct.number = RX_SIZE;
    dma_init_struct.periph_addr = (uint32_t)&USART_DATA(USART0);
    dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
    dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT;
    dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
    dma_init(DMA0, DMA_CH4, &dma_init_struct);

    dma_circulation_disable(DMA0, DMA_CH3);
    dma_memory_to_memory_disable(DMA0, DMA_CH3);
    dma_circulation_disable(DMA0, DMA_CH4);
    dma_memory_to_memory_disable(DMA0, DMA_CH4);

    usart_dma_transmit_config(USART0, USART_TRANSMIT_DMA_ENABLE);
    dma_channel_enable(DMA0, DMA_CH3);
    usart_dma_receive_config(USART0, USART_RECEIVE_DMA_ENABLE);
    dma_channel_enable(DMA0, DMA_CH4);
#endif
    nvic_irq_enable(USART0_IRQn, 5, 1);
    usart_interrupt_enable(USART0, USART_INT_IDLE);
}

/*******************************************************************
 * 函数名: bsp_usart2_init()
 * 功 能:
 * 输 入:
 * 输 出:
 *******************************************************************/
static void bsp_usart2_init(bsp_uart_driver_t *drv)
{
    rcu_periph_clock_enable(RCU_USART0);
    rcu_periph_clock_enable(RCU_GPIOA);
    rcu_periph_clock_enable(RCU_DMA0);

    gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_9);
    gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_10);

    /* TX */
    gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP,GPIO_PIN_9);
    gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_9);

    /* RX */
    gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP,GPIO_PIN_10);
    gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_10);

    usart_deinit(USART0);
    usart_baudrate_set(USART0, 115200U);
    usart_word_length_set(USART0, USART_WL_8BIT);
    usart_stop_bit_set(USART0, USART_STB_1BIT);
    usart_parity_config(USART0, USART_PM_NONE);
    usart_hardware_flow_rts_config(USART0, USART_RTS_DISABLE);
    usart_hardware_flow_cts_config(USART0, USART_CTS_DISABLE);
    usart_receive_config(USART0, USART_RECEIVE_ENABLE);
    usart_transmit_config(USART0, USART_TRANSMIT_ENABLE);
    usart_enable(USART0);
	#if 0
    // TX
    dma_parameter_struct dma_init_struct;
    dma_deinit(DMA0, DMA_CH3);
    dma_struct_para_init(&dma_init_struct);
    dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL;
    dma_init_struct.memory_addr = NULL;
    dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
    dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;
    dma_init_struct.number = 0;
    dma_init_struct.periph_addr = (uint32_t)&USART_DATA(USART0);
    dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
    dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT;
    dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
    dma_init(DMA0, DMA_CH3, &dma_init_struct);
    // RX
    dma_deinit(DMA0, DMA_CH4);
    dma_struct_para_init(&dma_init_struct);
    dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY;
    dma_init_struct.memory_addr = (uint32_t)(drv->port.rx_buff);
    dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
    dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;
    dma_init_struct.number = RX_SIZE;
    dma_init_struct.periph_addr = (uint32_t)&USART_DATA(USART0);
    dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
    dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT;
    dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
    dma_init(DMA0, DMA_CH4, &dma_init_struct);

    dma_circulation_disable(DMA0, DMA_CH3);
    dma_memory_to_memory_disable(DMA0, DMA_CH3);
    dma_circulation_disable(DMA0, DMA_CH4);
    dma_memory_to_memory_disable(DMA0, DMA_CH4);

    usart_dma_transmit_config(USART0, USART_TRANSMIT_DMA_ENABLE);
    dma_channel_enable(DMA0, DMA_CH3);
    usart_dma_receive_config(USART0, USART_RECEIVE_DMA_ENABLE);
    dma_channel_enable(DMA0, DMA_CH4);
	#endif

    nvic_irq_enable(USART0_IRQn, 5, 2);
    usart_interrupt_enable(USART0, USART_INT_IDLE);
}

/*******************************************************************
 * 函数名: bsp_usart3_init()
 * 功 能:
 * 输 入:
 * 输 出:
 *******************************************************************/
static void bsp_usart3_init(bsp_uart_driver_t *drv)
{
    rcu_periph_clock_enable(RCU_UART3);
    rcu_periph_clock_enable(RCU_GPIOA);
    rcu_periph_clock_enable(RCU_DMA0);

    gpio_af_set(GPIOA, GPIO_AF_8, GPIO_PIN_0); // TX
    gpio_af_set(GPIOA, GPIO_AF_8, GPIO_PIN_1); // RX

    /* TX */
    gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP,GPIO_PIN_0);
    gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_0);

    /* RX */
    gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP,GPIO_PIN_1);
    gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_1);

    usart_deinit(UART3);
    usart_baudrate_set(UART3, 9600U);
    usart_receive_config(UART3, USART_RECEIVE_ENABLE);
    usart_transmit_config(UART3, USART_TRANSMIT_ENABLE);
    usart_dma_receive_config(UART3, USART_RECEIVE_DMA_ENABLE);

	dma_single_data_parameter_struct dma_init_struct;
#if 0
    // TX    
    dma_deinit(DMA1, DMA_CH5);
    dma_struct_para_init(&dma_init_struct);
    dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL;
    dma_init_struct.memory_addr = NULL;
    dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
    dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;
    dma_init_struct.number = 0;
    dma_init_struct.periph_addr = (uint32_t)&USART_DATA(UART3);
    dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
    dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT;
    dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
    dma_init(DMA1, DMA_CH5, &dma_init_struct);
#endif
    // RX
    dma_deinit(DMA0, DMA_CH2);

    dma_init_struct.memory0_addr = (uint32_t)(&drv->port.rx_buff);
    dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
    dma_init_struct.number = RX_SIZE;
    dma_init_struct.periph_addr = (uint32_t)&USART_DATA(UART3);
    dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
    dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
    dma_init_struct.periph_memory_width = DMA_PERIPH_WIDTH_8BIT;
    dma_init_struct.direction = DMA_PERIPH_TO_MEMORY;

    dma_single_data_mode_init(DMA0, DMA_CH2, &dma_init_struct);
    dma_channel_subperipheral_select(DMA0, DMA_CH2, DMA_SUBPERI4);
    dma_circulation_disable(DMA0, DMA_CH2);
    dma_channel_enable(DMA0, DMA_CH2);

    nvic_irq_enable(UART3_IRQn, 5, 1);
    usart_interrupt_enable(UART3, USART_INT_IDLE);
    usart_enable(UART3);
}
